package com.swiftride.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.swiftride.constants.Constants;
import com.swiftride.constants.GlobalExceptionCode;
import com.swiftride.exception.GlobalException;
import com.swiftride.mapper.DriverAuthMaterialMapper;
import com.swiftride.pojo.domain.Driver;
import com.swiftride.pojo.domain.DriverAuthMaterial;
import com.swiftride.pojo.domain.DriverMaterialAuthLog;
import com.swiftride.pojo.dto.DriverAuthMaterialDto;
import com.swiftride.service.IDriverAuthMaterialService;
import com.swiftride.service.IDriverMaterialAuthLogService;
import com.swiftride.service.IDriverService;
import com.swiftride.utils.AssertUtil;
import com.swiftride.utils.BitStatesUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;

/**
 * <p>
 * 司机实名资料 服务实现类
 * </p>
 *
 * @author wy
 * @since 2024-07-27
 */
@Service
public class DriverAuthMaterialServiceImpl extends ServiceImpl<DriverAuthMaterialMapper, DriverAuthMaterial> implements IDriverAuthMaterialService {

    @Autowired
    private IDriverService driverService;

    @Autowired
    private IDriverMaterialAuthLogService driverMaterialAuthLogService;

    @Transactional
    @Override
    public void authMaterial(DriverAuthMaterial driverAuthMaterial) {
        //1.参数校验 使用jsr303完成

        //2.业务校验
        //2.1获取司机对象
        Long driverId = StpUtil.getLoginIdAsLong();
        Driver driver = driverService.getById(driverId);
        AssertUtil.isNotNull(driver, GlobalExceptionCode.PARAM_PHONE_NOT_EXIST);
        //2.2查询司机实名认证对象
        DriverAuthMaterial driverAuthMaterialFromDb = super.getOne(new LambdaQueryWrapper<DriverAuthMaterial>()
                .eq(DriverAuthMaterial::getDriverId, driverId));
        //认证状态不为审核中或者不为审核通过才能认证
        if (ObjectUtil.isNotNull(driverAuthMaterialFromDb)) {
            Integer realAuthStatus = driverAuthMaterialFromDb.getRealAuthStatus();
            if (Constants.RealAuth.VERIFYING.equals(realAuthStatus) || Constants.RealAuth.APPROVED.equals(realAuthStatus)) {
                throw new GlobalException(GlobalExceptionCode.PARAM_ERROR);
            }
        }
        //3.业务实现
        //3.1修改司机实名认证对象
        driverAuthMaterial.init();
        driverAuthMaterial.setRealAuthStatus(Constants.RealAuth.VERIFYING);
        driverAuthMaterial.setDriverId(driverId);
        if (ObjectUtil.isNull(driverAuthMaterialFromDb)) {
            super.save(driverAuthMaterial);
        } else {
            super.updateById(driverAuthMaterial);
        }
        //3.2更新司机位状态--添加实名认证中的状态
        long bitState = BitStatesUtil.addState(driver.getBitState(), BitStatesUtil.OP_REAL_AUTHENTICATING);
        driver.setBitState(bitState);
        //3.3存储司机信息
        driver.setUpdateTime(new Date());
        driverService.updateById(driver);
    }

    @Transactional
    @Override
    public void audit(DriverAuthMaterialDto driverAuthMaterialDto) {
        //1.参数校验
        //2.业务校验
        //2.1 获取司机实名信息
        Long authMaterialId = driverAuthMaterialDto.getId();
        DriverAuthMaterial driverAuthMaterial = super.getById(authMaterialId);
        AssertUtil.isNotNull(driverAuthMaterial, GlobalExceptionCode.PARAM_ERROR);

        //2.2 获取司机信息
        Long driverId = driverAuthMaterial.getDriverId();
        Driver driver = driverService.getById(driverId);
        AssertUtil.isNotNull(driver, GlobalExceptionCode.PARAM_PHONE_NOT_EXIST);

        //2.3 判断司机是否在实名中
        //司机信息当前位状态
        Long bitState = driver.getBitState();
        if (!BitStatesUtil.hasState(bitState, BitStatesUtil.OP_REAL_AUTHENTICATING)) {
            throw new GlobalException(GlobalExceptionCode.PARAM_ERROR);
        }

        //3.业务实现
        //3.1更新司机实名认证的审核信息
        long loginId = StpUtil.getLoginIdAsLong();
        Date date = new Date();
        String remark = driverAuthMaterialDto.getRemark();
        driverAuthMaterial.setAuditTime(date);
        driverAuthMaterial.setAuditUserId(loginId);
        driverAuthMaterial.setAuditRemark(remark);
        driverAuthMaterial.setUpdateTime(date);

        //3.2初始化操作日志
        DriverMaterialAuthLog driverMaterialAuthLog = new DriverMaterialAuthLog();
        driverMaterialAuthLog.init();
        driverMaterialAuthLog.setAuthMaterialId(authMaterialId);
        driverMaterialAuthLog.setAuditTime(date);
        driverMaterialAuthLog.setUpdateTime(date);
        driverMaterialAuthLog.setAuditUserId(loginId);
        driverMaterialAuthLog.setAuditRemark(remark);

        //3.3根据审核结果修改信息
        //司机信息--删除审核中的状态位
        long state = BitStatesUtil.removeState(bitState, BitStatesUtil.OP_REAL_AUTHENTICATING);
        //根据审核结果修改表状态
        if (driverAuthMaterialDto.getApprove()) {
            //更新司机位状态信息--实名认证成功
            state = BitStatesUtil.addState(state, BitStatesUtil.OP_REAL_AUTHENTICATED);
            //审核通过--更新司机实名认证状态
            driverAuthMaterial.setRealAuthStatus(Constants.RealAuth.APPROVED);
            //审核通过--更新司机实名认证操作日志状态
            driverMaterialAuthLog.setRealAuthStatus(Constants.RealAuth.APPROVED);
        } else {
            //审核不通过--更新司机实名认证状态
            driverAuthMaterial.setRealAuthStatus(Constants.RealAuth.VERIFY_FAIL);
            //审核不通过--更新司机实名认证操作日志状态
            driverMaterialAuthLog.setRealAuthStatus(Constants.RealAuth.VERIFY_FAIL);
        }
        //更新司机信息位状态信息
        driver.setBitState(state);
        driver.setUpdateTime(date);
        driverService.updateById(driver);
        //更新司机实名认证信息
        super.updateById(driverAuthMaterial);
        //更新司机实名认证操作日志
        driverMaterialAuthLogService.save(driverMaterialAuthLog);
    }

    @Override
    public DriverAuthMaterial getDriverAuthInfo() {
        //2.1获取司机对象
        Long driverId = StpUtil.getLoginIdAsLong();
        //查询司机实名认证对象
        return super.getOne(new LambdaQueryWrapper<DriverAuthMaterial>()
                .eq(DriverAuthMaterial::getDriverId, driverId)
                .last("limit 1"));
    }
}
